import base64
import os
import sys
import argparse
import logging
from logging.handlers import TimedRotatingFileHandler
import azure.cognitiveservices.speech as speechsdk
import uuid
from datetime import datetime
import socket

def setup_logger():
    """设置日志记录器"""
    # 创建logger
    logger = logging.getLogger(__name__)
    logger.setLevel(logging.INFO)
    
    # 清除现有的处理器，避免重复添加
    logger.handlers.clear()
    
    # 创建控制台处理器
    console_handler = logging.StreamHandler(sys.stdout)
    console_handler.setLevel(logging.INFO)
    
    # 为每个进程创建唯一的日志文件名
    timestamp = datetime.now().strftime("%Y%m%d")
    process_id = os.getpid()
    unique_id = uuid.uuid4().hex[:8]
    log_filename = f'tts_{process_id}_{unique_id}.log'
    
    # 确保日志目录存在
    log_dir = os.path.join('log', timestamp)
    os.makedirs(log_dir, exist_ok=True)
    log_filename = os.path.join(log_dir, log_filename)
    
    # 创建按天分割的日志文件处理器
    file_handler = TimedRotatingFileHandler(
        filename=log_filename,
        when='midnight',
        interval=1,
        backupCount=30,
        encoding='utf-8'
    )
    file_handler.setLevel(logging.INFO)
    
    # 创建格式化器
    formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s')
    console_handler.setFormatter(formatter)
    file_handler.setFormatter(formatter)
    
    # 将处理器添加到logger
    logger.addHandler(console_handler)
    logger.addHandler(file_handler)
    
    return logger


def check_network_connectivity(endpoint):
    """检查网络连接性"""
    logger = setup_logger()
    try:
        # 移除协议前缀
        host = endpoint.replace('https://', '').replace('http://', '').split('/')[0]
        if ':' in host:
            host, port = host.split(':')
            port = int(port)
        else:
            port = 443 if endpoint.startswith('https://') else 80
            
        logger.info(f"Testing connectivity to {host}:{port}")
        sock = socket.create_connection((host, port), timeout=10)
        sock.close()
        logger.info("Network connectivity test passed")
        return True
    except Exception as e:
        logger.error(f"Network connectivity test failed: {str(e)}")
        return False


def synthesize_speech(text, speech_key, endpoint, voiceSampleRate, fileName):
    """
    使用Azure Text-to-Speech合成语音
    
    Args:
        :param fileName:
        :param text:  要合成的文本
        :param speech_key: Azure语音服务密钥
        :param endpoint: Azure语音服务终结点
        :param voiceSampleRate:
    """
    logger = setup_logger()
    
    # 检查网络连接
    if not check_network_connectivity(endpoint):
        logger.error("Network connectivity check failed. Please check your network connection.")
        return False
    
    # 创建语音配置，使用传入的密钥和写死的终结点
    try:
        speech_config = speechsdk.SpeechConfig(subscription=speech_key, endpoint=endpoint)
        logger.info(f"SpeechConfig created with endpoint: {endpoint}")
    except Exception as e:
        logger.error(f"Failed to create SpeechConfig: {str(e)}")
        return False
        
    # 文件保存到fileName
    try:
        audio_config = speechsdk.audio.AudioOutputConfig(use_default_speaker=False, filename=fileName)
        logger.info(f"AudioOutputConfig created with filename: {fileName}")
    except Exception as e:
        logger.error(f"Failed to create AudioOutputConfig: {str(e)}")
        return False

    # 设置语音合成声音
    # speech_config.speech_synthesis_voice_name = 'en-US-AvaMultilingualNeural'

    tempFormat = speechsdk.SpeechSynthesisOutputFormat.Audio24Khz48KBitRateMonoMp3
    if voiceSampleRate == 24:
        tempFormat = speechsdk.SpeechSynthesisOutputFormat.Audio24Khz48KBitRateMonoMp3
    elif voiceSampleRate == 16:
        tempFormat = speechsdk.SpeechSynthesisOutputFormat.Audio16Khz32KBitRateMonoMp3
    elif voiceSampleRate == 8:
        tempFormat = speechsdk.SpeechSynthesisOutputFormat.Riff8Khz16BitMonoPcm
    elif voiceSampleRate == 48:
        tempFormat = speechsdk.SpeechSynthesisOutputFormat.Audio48Khz96KBitRateMonoMp3
    speech_config.set_speech_synthesis_output_format(tempFormat)

    # 创建语音合成器
    try:
        speech_synthesizer = speechsdk.SpeechSynthesizer(speech_config=speech_config, audio_config=audio_config)
        logger.info("SpeechSynthesizer created successfully")
    except Exception as e:
        logger.error(f"Failed to create SpeechSynthesizer: {str(e)}")
        return False

    # 合成语音
    try:
        logger.info("Starting speech synthesis...")
        speech_synthesis_result = speech_synthesizer.speak_ssml_async(text).get()
        logger.info("Speech synthesis completed")
    except Exception as e:
        logger.error(f"Failed during speech synthesis: {str(e)}")
        return False

    # 处理结果
    if speech_synthesis_result.reason == speechsdk.ResultReason.SynthesizingAudioCompleted:
        # logger.info("Speech synthesized for text [{}]".format(text))
        return True
    elif speech_synthesis_result.reason == speechsdk.ResultReason.Canceled:
        cancellation_details = speech_synthesis_result.cancellation_details
        logger.error("Speech synthesis canceled: {}".format(cancellation_details.reason))
        if cancellation_details.reason == speechsdk.CancellationReason.Error:
            if cancellation_details.error_details:
                logger.error("Error details: {}".format(cancellation_details.error_details))
            logger.error("Check your speech resource key and endpoint values")
        return False


def main():
    # 设置日志记录器
    logger = setup_logger()
    
    try:
        # 设置命令行参数解析
        parser = argparse.ArgumentParser(description='Azure Text-to-Speech CLI')
        parser.add_argument('--text', '-t', required=True, help='Text to synthesize')
        parser.add_argument('--key', '-k', required=True, help='Azure Speech Service subscription key')
        parser.add_argument('--endpoint', '-e', required=True, default='https://chinanorth2.tts.speech.azure.cn/',
                            help='Azure Speech Service endpoint')
        parser.add_argument('--voiceSampleRate', '-s', required=False, default=24, help='voice sample rate')
        parser.add_argument('--fileName', '-f', required=False, default='./output.mp3', help='output file name')

        args = parser.parse_args()

        # 确保输出文件的目录存在
        os.makedirs(os.path.dirname(os.path.abspath(args.fileName)), exist_ok=True)

        # 解码
        try:
            decoded_bytes = base64.b64decode(args.text)
            decoded_str = decoded_bytes.decode('utf-8')
        except Exception as e:
            logger.error("Failed to decode base64 text: {}".format(str(e)))
            return 2  # 参数错误返回码

        logger.info("Azure Text-to-Speech CLI")
        logger.info("Endpoint: {}".format(args.endpoint))
        logger.info("Voice Sample Rate: {}".format(args.voiceSampleRate))
        logger.info("Output File Name: {}".format(args.fileName))
        # 调用语音合成函数
        success = synthesize_speech(decoded_str, args.key, args.endpoint, int(args.voiceSampleRate), args.fileName)

        if success:
            logger.info("Speech synthesis completed successfully. Output saved to {}".format(args.fileName))
            return 0  # 成功返回码
        else:
            logger.error("Speech synthesis failed.")
            return 1  # 失败返回码
    except Exception as e:
        logger.error("Unexpected error occurred: {}".format(str(e)))
        return 3  # 未预期错误返回码


if __name__ == "__main__":
    exit_code = main()
    sys.exit(exit_code)